import 'dart:io';
import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:mime/mime.dart';
import './core/upload_task_manager.dart';
import './core/chunk_upload_client.dart';
import '../../models/chunk_upload.dart';
import '../../models/api_response.dart';
import '../../config/upload_config.dart';

/// 分片上传服务，对外提供上传接口
class ChunkUploadService {
  // 上传任务管理器
  static final _taskManager = UploadTaskManager();

  // API客户端
  static final _client = ChunkUploadClient();

  // 单例模式实现
  static final ChunkUploadService _instance = ChunkUploadService._internal();
  factory ChunkUploadService() => _instance;
  ChunkUploadService._internal();

  /// 获取上传任务流
  static Stream<List<UploadTask>> get uploadTasksStream =>
      UploadTaskManager.uploadTasksStream;

  /// 获取上传任务列表
  static List<UploadTask> get uploadTasks => UploadTaskManager.uploadTasks;

  /// 初始化分片上传
  static Future<ApiResponse<ChunkUploadInitResponse>> initChunkUpload({
    required String fileName,
    required int fileSize,
    int chunkSize = UploadConfig.chunkSize,
    required String mimeType,
    int directoryId = 0,
  }) {
    return _client.initChunkUpload(
      fileName: fileName,
      fileSize: fileSize,
      chunkSize: chunkSize,
      mimeType: mimeType,
      directoryId: directoryId,
    );
  }

  /// 获取上传状态
  static Future<ApiResponse<ChunkUploadStatusResponse>> getUploadStatus(
    String taskId,
  ) {
    return _client.getUploadStatus(taskId);
  }

  /// 完成上传
  static Future<ApiResponse<ChunkUploadCompleteResponse>> completeUpload(
    String taskId,
  ) {
    return _client.completeUpload(taskId);
  }

  /// 取消上传
  static Future<ApiResponse<AbortUploadResponse>> abortUpload(String taskId) {
    return _client.abortUpload(taskId);
  }

  /// 添加上传任务
  static Future<(UploadTask task, bool isLargeFile)> addUploadTask({
    required String filePath,
    required String fileName,
    required int fileSize,
    required String mimeType,
    int directoryId = 0,
  }) {
    return _taskManager.addUploadTask(
      filePath: filePath,
      fileName: fileName,
      fileSize: fileSize,
      mimeType: mimeType,
      directoryId: directoryId,
    );
  }

  /// 开始上传任务
  static Future<void> startUploadTask(String taskId) {
    return _taskManager.startUploadTask(taskId);
  }

  /// 暂停上传任务
  static Future<void> pauseUploadTask(String taskId) {
    return _taskManager.pauseUploadTask(taskId);
  }

  /// 恢复上传任务
  static Future<void> resumeUploadTask(String taskId) {
    return _taskManager.resumeUploadTask(taskId);
  }

  /// 取消上传任务
  static Future<void> cancelUploadTask(String taskId) {
    return _taskManager.cancelUploadTask(taskId);
  }

  /// 移除上传任务
  static void removeUploadTask(String taskId) {
    _taskManager.removeUploadTask(taskId);
  }

  /// 清除已完成的任务
  static void clearCompletedTasks() {
    _taskManager.clearCompletedTasks();
  }

  /// 上传完整文件的简化方法
  Future<void> uploadFile({
    required File file,
    required String filename,
    required int directoryId,
    Function(double)? onProgress,
  }) async {
    debugPrint('准备上传文件: $filename, 目录ID: $directoryId');

    try {
      // 文件大小
      final fileSize = await file.length();

      // 获取MIME类型
      final mimeType = lookupMimeType(file.path) ?? 'application/octet-stream';

      // 初始化上传任务
      final (task, _) = await addUploadTask(
        filePath: file.path,
        fileName: filename,
        fileSize: fileSize,
        mimeType: mimeType,
        directoryId: directoryId,
      );

      // 上传开始时间
      final startTime = DateTime.now().millisecondsSinceEpoch;

      // 监听上传进度
      if (onProgress != null) {
        Timer.periodic(const Duration(milliseconds: 500), (timer) {
          // 获取任务状态
          final currentTask = uploadTasks.firstWhere(
            (t) => t.id == task.id,
            orElse: () => task,
          );

          // 计算进度
          if (currentTask.status == UploadTaskStatus.uploading) {
            final progress =
                (currentTask.uploadedBytes / currentTask.fileSize).toDouble();
            onProgress(progress);
          } else if (currentTask.status == UploadTaskStatus.completed ||
              currentTask.status == UploadTaskStatus.failed ||
              currentTask.status == UploadTaskStatus.canceled) {
            // 上传完成或失败，取消定时器
            timer.cancel();

            // 完成时回调进度100%
            if (currentTask.status == UploadTaskStatus.completed) {
              onProgress(1.0);
            }
          }
        });
      }

      // 开始上传
      await startUploadTask(task.id);

      // 等待上传完成
      await _waitForUploadCompletion(task.id);

      // 计算总用时
      final endTime = DateTime.now().millisecondsSinceEpoch;
      final duration = (endTime - startTime) / 1000;

      debugPrint('文件上传完成: $filename, 用时: ${duration.toStringAsFixed(1)}秒');
    } catch (e) {
      debugPrint('文件上传失败: $e');
      rethrow;
    }
  }

  /// 等待上传完成
  Future<void> _waitForUploadCompletion(String taskId) async {
    // 最大等待时间 10 分钟
    final maxWaitTime = Duration(minutes: 10);
    final startTime = DateTime.now();

    while (true) {
      // 检查是否超时
      if (DateTime.now().difference(startTime) > maxWaitTime) {
        throw Exception('上传超时');
      }

      // 查找任务
      final taskIndex = uploadTasks.indexWhere((task) => task.id == taskId);

      // 任务不存在
      if (taskIndex == -1) {
        throw Exception('上传任务不存在');
      }

      final task = uploadTasks[taskIndex];

      // 上传完成
      if (task.status == UploadTaskStatus.completed) {
        return;
      }

      // 上传失败
      if (task.status == UploadTaskStatus.failed ||
          task.status == UploadTaskStatus.canceled) {
        throw Exception('上传失败: ${task.error ?? "未知错误"}');
      }

      // 等待一段时间后再检查
      await Future.delayed(Duration(milliseconds: 300));
    }
  }

  /// 上传文件并提供回调
  Future<String> uploadFileWithCallbacks(
    String filePath,
    UploadTaskConfig config, {
    Function(double progress, double speed)? onProgress,
    Function(bool success, String? url)? onComplete,
  }) async {
    try {
      // 获取文件信息
      final file = File(filePath);
      if (!file.existsSync()) {
        throw Exception('文件不存在: $filePath');
      }

      // 获取文件名和大小
      final fileName = file.path.split('/').last;
      final fileSize = file.lengthSync();

      // 估计MIME类型
      final mimeType = lookupMimeType(filePath) ?? 'application/octet-stream';

      // 创建并添加上传任务到任务管理器（而不是仅创建任务）
      final (task, _) = await _taskManager.addUploadTask(
        filePath: filePath,
        fileName: fileName,
        fileSize: fileSize,
        mimeType: mimeType,
        directoryId: config.directoryId, // 使用配置中的目录ID
      );
      final taskId = task.id;

      debugPrint('开始上传任务: $taskId');

      // 开始上传任务
      await startUploadTask(taskId);

      // 监听上传进度
      if (onProgress != null) {
        Timer.periodic(const Duration(milliseconds: 300), (timer) {
          // 获取任务状态
          final currentTask = uploadTasks.firstWhere(
            (t) => t.id == taskId,
            orElse: () => task,
          );

          // 计算进度和速度
          if (currentTask.status == UploadTaskStatus.uploading) {
            // 使用原始进度值，不需要除以100
            final progress = currentTask.progress;
            // 简单估算速度，单位为KB/s
            final elapsedTime =
                DateTime.now()
                    .difference(currentTask.createdAt)
                    .inMilliseconds /
                1000;
            final speed =
                elapsedTime > 0
                    ? ((currentTask.uploadedBytes / 1024) / elapsedTime)
                        .toDouble()
                    : 0.0;

            onProgress(progress, speed);
          } else if (currentTask.status == UploadTaskStatus.completed ||
              currentTask.status == UploadTaskStatus.failed ||
              currentTask.status == UploadTaskStatus.canceled) {
            // 上传完成或失败，取消定时器
            timer.cancel();

            // 完成时回调
            if (currentTask.status == UploadTaskStatus.completed &&
                onComplete != null) {
              // 添加更多日志以调试
              debugPrint('任务完成，获取响应数据: ${currentTask.responseData}');

              // 获取上传结果URL
              String? url;
              if (currentTask.responseData != null) {
                // 检查是否有嵌套的data字段
                if (currentTask.responseData!.containsKey('data') &&
                    currentTask.responseData!['data'] is Map<String, dynamic>) {
                  // 从嵌套的data字段中获取storage_path
                  final data =
                      currentTask.responseData!['data'] as Map<String, dynamic>;
                  url = data['storage_path'] as String?;
                  debugPrint('从data字段获取URL: $url');
                } else {
                  // 直接从顶层字段获取storage_path
                  url = currentTask.responseData!['storage_path'] as String?;
                  debugPrint('从顶层字段获取URL: $url');
                }
              }

              // 确保任务完成时总是报告成功
              onComplete(true, url);
            } else if (onComplete != null) {
              onComplete(false, null);
            }
          }
        });
      }

      return taskId;
    } catch (e) {
      debugPrint('创建上传任务失败: $e');
      if (onComplete != null) {
        onComplete(false, null);
      }
      rethrow;
    }
  }

  /// 取消所有正在进行的上传任务
  static void cancelAllTasks() {
    for (var task in uploadTasks) {
      if (task.status == UploadTaskStatus.uploading ||
          task.status == UploadTaskStatus.pending ||
          task.status == UploadTaskStatus.paused) {
        cancelUploadTask(task.id);
      }
    }
  }

  /// 销毁服务
  static void dispose() {
    // 取消所有正在上传的任务
    cancelAllTasks();
  }
}
